package com.mingben.betplatform.api;

import com.alibaba.fastjson.JSONObject;
import com.mingben.betplatform.api.pk6758.BetStringFactory;
import com.mingben.betplatform.dto.pk6758.OpenHistory;
import com.mingben.betplatform.exception.*;
import com.mingben.betplatform.util.LogUtil;
import com.mingben.betplatform.util.ThreadUtil;
import com.mingben.betplatform.util.feifei.FeiFeiApi;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * official url : https://www.2940011.com:9885/
 * 包含登錄 下注接口
 */
public class Russian294Api {
    private Logger logger = LoggerFactory.getLogger(Russian294Api.class);
    private String username;
    private String password;
    //http client cookie
    private CookieStore cookieStore = new BasicCookieStore();
    //http client
    private HttpClient client = HttpClients.custom().setDefaultCookieStore(cookieStore).build();

    private String uuid;

    //当前期号
    private String currentPeriod = "";

    private String baseUrl = "http://www.2940011.com:9885";
    public Russian294Api(String username , String password ){
        this.username = username;
        this.password = password;
    }

    public void login(){
        //登錄前 獲取綁定的session
        try {
            for(int i=0;i<10;i++){
                String verifyBefore = getVerifyBefore();

                String kapatchaPath = getVerfiyPath(verifyBefore);

                String captcha = new FeiFeiApi().recognize4Number4Letter(kapatchaPath);

//            retriverSession();
                //將session綁定到當前登錄人
                doLogin(username , password , captcha , verifyBefore.split(";")[1] );
            }

            //獲取 uid 請求開獎結果需要
//            retriveUUid();
//
//            //可下注时间是否已到
//            boolean betTimeReachable = false;
//            while(betTimeReachable == false){
//                //下午一点的秒数对于今天 1:06分销售彩票
//                long afternoonOneClock = 13 * 60 * 60  + 6 * 60 ;
//                long delayToWait = afternoonOneClock - LocalTime.now().get(ChronoField.SECOND_OF_DAY) ;
//                if( delayToWait > 0){
//                    betTimeReachable = false;
//                    logger.error("距离开盘时间 ," + delayToWait +"秒");
//                    ThreadUtil.sleep10s();
//                }else{
//                    betTimeReachable = true;
//                }
//            }
//            //是否轮训获取到下期期号
//            while(true){
//                //獲取開獎結果
//                OpenHistory openHistory = retriveOpenHistory();
//                if(!currentPeriod.equals(openHistory.getOpenNumList().getNewnumber())){
//                    //下注
//                    bet(openHistory);
//                    currentPeriod = openHistory.getOpenNumList().getNewnumber();
//                }
//                //休眠十秒 节省cpu
//                ThreadUtil.sleep10s();
//            }

        } catch (SessionRetriveException e) {
            e.printStackTrace();
        } catch (UuidRetriveException e) {
            e.printStackTrace();
        } catch (LoginFailedException e) {
            e.printStackTrace();
        } catch (BetFailureException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 获取验证码前置参数
     *
     * @return
     */
    public String getVerifyBefore() {
        String url = baseUrl + "/infe/verify/mkcode?_=0.86498886432721221541129057496";

        HttpGet httpGet = new HttpGet(url);

        httpGet.addHeader(new BasicHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0) Gecko/20100101 Firefox/63.0"));
        try {
            HttpResponse httpResponse = client.execute(httpGet);

            HttpEntity httpEntity = httpResponse.getEntity();

            String resp = EntityUtils.toString(httpEntity, Charset.defaultCharset());
            return resp;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getVerfiyPath(String verifyBefore) {
        if (verifyBefore.split(";").length != 3) {
            throw new IllegalArgumentException("获取verifyBefore失败");
        }
        String userHome = System.getProperty("user.home");
        String url = baseUrl + "/infe/verify/macpic?SR=" + verifyBefore.split(";")[1];

        Map<String, String> headerParams = new HashMap();
        headerParams.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:63.0) Gecko/20100101 Firefox/63.0");
        try {
            HttpGet httpGet = new HttpGet(url);
            if (headerParams != null && headerParams.size() > 0) {
                for (Map.Entry<String, String> entry : headerParams.entrySet()) {
                    httpGet.addHeader(new BasicHeader(entry.getKey(), entry.getValue()));
                }
            }

            HttpResponse response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent();
            File targetFile = new File(userHome + "/" + System.currentTimeMillis() + ".png");
            FileUtils.copyToFile(inputStream, targetFile);
            return targetFile.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 下注
     */
    private void bet(OpenHistory openHistory ) throws BetFailureException {

        //看開獎結果1在哪位  從0開始算
        int index = whereOneIn(openHistory);
        logger.info("1号马在第"+( index + 1) +"赛道,,");
        String sortAry = BetStringFactory.getBetString(String.valueOf(index));
        String url = "http://www.pk6758.com/Member/DownEntry.aspx?t="+uuid;
        HttpPost betPost = new HttpPost(url);
        betPost.setHeader("Content-Type" , "application/x-www-form-urlencoded");
        betPost.setHeader("User-Agent" , " Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0");
        betPost.setHeader("Referer" , " http://www.pk6758.com/Member/LoginValidate.aspx");
        //cookie client自動管理
        NameValuePair gamePair = new BasicNameValuePair("gameIndex" , "8");
        //投注结果知晓的下一期
        NameValuePair numberPair = new BasicNameValuePair("number" , String.valueOf(Long.valueOf(openHistory.getOpenNumList().getNewnumber()) + 1));
        NameValuePair sortAryPair = new BasicNameValuePair("sortAry" , sortAry);
        NameValuePair typePair = new BasicNameValuePair("dataType" , "2");
        List<NameValuePair> valuePairs = Arrays.asList(gamePair , numberPair , sortAryPair , typePair);
        try {
            betPost.setEntity(new UrlEncodedFormEntity(valuePairs , "utf8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            HttpResponse response = client.execute(betPost);
            String respStr = EntityUtils.toString(response.getEntity());
            if(respStr.contains("已封盤")){
                LogUtil.requestLogger("已封盘 ," , url , valuePairs.stream().map( valuePair -> valuePair.getName() + ":" + valuePair.getValue() + " , ").collect(Collectors.joining() ),respStr );
                ThreadUtil.sleep5s();
                //retry
                bet(openHistory);
            }
            if(!respStr.contains("usableCredit")){
                LogUtil.requestLogger("下注失敗 ," , url ,  valuePairs.toString() , respStr );
                throw new BetFailureException("下注失敗");
            }
            logger.info("下注成功,,,");
        } catch (IOException e) {
            throw new BetFailureException("下注失敗");
        }
    }
    //
    private int whereOneIn(OpenHistory openHistory) {
        List<Integer> numbers = openHistory.getOpenNumList().getNumList();
        for(int index = 0 ; index < numbers.size() ; index ++ ){
            Integer number = numbers.get(index);
            if(number.intValue() == 1){
                return index;
            }
        }
        return -1;
    }

    /**
     * 獲取開獎結果
     */
    private OpenHistory retriveOpenHistoryOnce() throws OpenHistoryRetriveException {

        String url = "http://www.pk6758.com/Member/Game_KC.aspx";
        HttpPost historyPost = new HttpPost(url);
        historyPost.setHeader("Content-Type" , "application/x-www-form-urlencoded");
        historyPost.setHeader("User-Agent" , " Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0");
        historyPost.setHeader("Referer" , " http://www.pk6758.com/Member/LoginValidate.aspx");
        //cookie client自動管理
        NameValuePair uuidPair = new BasicNameValuePair("t" , uuid);
        NameValuePair gamePair = new BasicNameValuePair("gameIndex" , "8");
        NameValuePair typePair = new BasicNameValuePair("type" , "1");
        List<NameValuePair> valuePairs = Arrays.asList(uuidPair , gamePair , typePair);
        try {
            historyPost.setEntity(new UrlEncodedFormEntity(valuePairs , "utf8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            HttpResponse response = client.execute(historyPost);
            String respStr = EntityUtils.toString(response.getEntity());
            if(!respStr.contains("win")){
                LogUtil.requestLogger("獲取開獎結果 ," , url ,  valuePairs.toString() , respStr );
                throw new OpenHistoryRetriveException();
            }
            OpenHistory openHistory =  JSONObject.parseObject(respStr , OpenHistory.class);
            logger.info("获取开奖结果成功,,");
            String openNumbersFormat = openHistory.getOpenNumList().getNumList()
                    .stream().map( number -> number + ",").collect(Collectors.joining());
            logger.info("开奖结果 " + openNumbersFormat);
            return openHistory;
        } catch (IOException e) {
            throw new OpenHistoryRetriveException();
        }
    }
    /**
     * 獲取開獎結果
     */
    private OpenHistory retriveOpenHistory() {
        try {
            return retriveOpenHistoryOnce();
        } catch (OpenHistoryRetriveException e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * html頁面找到uuid
     * @param content
     * @return
     */
    public String getUuid(String content){
        String canZhaoWu = "autoTid: \"";
        int start = content.indexOf(canZhaoWu) + canZhaoWu.length();
        int end = start + 32;
        return content.substring( start , end);
    }
    /**
     * 獲取uuid
     */
    private void retriveUUid() throws UuidRetriveException {
        String url = "http://www.pk6758.com/Member/";
        HttpGet uuidGet = new HttpGet(url);
        uuidGet.setHeader("Content-Type" , "application/x-www-form-urlencoded");
        uuidGet.setHeader("User-Agent" , " Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0");
        uuidGet.setHeader("Referer" , " http://www.pk6758.com/Member/LoginValidate.aspx");
        try {
            HttpResponse response = client.execute(uuidGet);
            String respStr = EntityUtils.toString(response.getEntity());
            String uuid = getUuid(respStr);
            if("".equals(uuid)){
                LogUtil.requestLogger("獲取uuid失敗 ,," , url , "" , respStr);
                throw new UuidRetriveException();
            }
            this.uuid = uuid;
            logger.info("获取uuid成功,,");
        } catch (IOException e) {
            throw new UuidRetriveException();
        }

    }

    /**
     * 登錄
     */
    private void doLogin(String username , String password , String captcha , String sr) throws LoginFailedException {
        String doLoginUrl = baseUrl + "/entrance/login.json?k=MzU2ZDRhNjViNzk3OTE3ZDc4YmI5N2YwNmFhOGZjMWRmNmExYWU0ZDBiN2RkMTk5MQ==" ; //+ Base64.encode();
        HttpPost loginPost = new HttpPost(doLoginUrl);
        loginPost.setHeader("Content-Type" , "application/x-www-form-urlencoded; charset=UTF-8");
        NameValuePair namePair = new BasicNameValuePair("username" , username);
        NameValuePair passPair = new BasicNameValuePair("password" , password);
        NameValuePair captchaPair = new BasicNameValuePair("captcha" , captcha);
        NameValuePair scenePair = new BasicNameValuePair("scene" , "nc_login");
        NameValuePair srPair = new BasicNameValuePair("sr" , sr);
        NameValuePair appPair = new BasicNameValuePair("appkey" , "");
        List<NameValuePair> valuePairs = Arrays.asList(namePair , passPair , captchaPair , scenePair , srPair , appPair);
        try {
            loginPost.setEntity(new UrlEncodedFormEntity(valuePairs , "utf8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        try {
            HttpResponse response = client.execute(loginPost);
            String respStr = EntityUtils.toString(response.getEntity());
//            if(!"1".equals(respStr)){
//                LogUtil.requestLogger("登陸失敗 ," , url ,  valuePairs.toString() , respStr );
//                throw new LoginFailedException();
//            }
            if(respStr.contains("uid")){
                logger.info("登录成功啦  , exit");
                System.exit(0);

            }
//            logger.info("登录成功,,{}" , respStr);
        } catch (IOException e) {
            throw new LoginFailedException();
        }
    }

    /**
     * 獲取session
     * @throws SessionRetriveException
     */
    private void
    retriverSession() throws SessionRetriveException {
        String url = "http://www.pk6758.com/";
        HttpGet sessionGet = new HttpGet(url);
        sessionGet.setHeader("Content-Type" , "application/x-www-form-urlencoded");
        try {
            HttpResponse response = client.execute(sessionGet);
            //校驗是否返回頭包含 Name = ASP.NET_SessionId

            List<Cookie> cookies = cookieStore.getCookies();
            for(Cookie c : cookies){
                if("ASP.NET_SessionId".equals(c.getName())){
                    if(c.getValue() == null){
                        throw new SessionRetriveException();
                    }
                    logger.info("获取session成功,,");
                    return;
                }
            }
            throw new SessionRetriveException();

        } catch (IOException e) {
            throw new SessionRetriveException();
        }
    }

}
